/*
 * File:   PIDdevice.h
 * Author: aple
 *
 * Created on 2015年10月9日, 上午10:07
 * v0.404
 */

#ifndef PIDDEVICE_H
#define	PIDDEVICE_H

#include "stdint.h"

#ifdef	__cplusplus
extern "C" {
#endif	

#ifdef   _PID_MODULE_
#define  PID_EXT
#else
#define  PID_EXT  extern
#endif

#define Q_VAL_1_0F                            (0x8000L)		//Q.15格式定点数 1
#define Q_VAL_0_5F                            (0x4000L)		//Q.15格式定点数 0.5
#define Q_VAL_0_25F                           (0x2000L)		//Q.15格式定点数 0.25
#define Q_VAL_0_125F                          (0x1000L)		//Q.15格式定点数 0.125
#define Q_VAL_NV1_0F                          (-0x8000L)	//Q.15格式定点数 1
#define Q_VAL_NV0_5F                          (-0x4000L)	//Q.15格式定点数 0.5
#define Q_VAL_NV0_25F                         (-0x2000L)	//Q.15格式定点数 0.25
#define Q_VAL_NV0_125F                        (-0x1000L)	//Q.15格式定点数 0.125

//参数表
#define _PID_P_POS     0
#define _PID_I_POS     1
#define _PID_D_POS     2
#define _PID_AR_POS    3
#define _PID_T_POS     4


	typedef enum
	{
		DWK_NONE = 0,
		DWK_DIR_UP,				//变化方向向上时削弱[-P~+P]->[1~(1-c)]
		DWK_DIR_DOWN,			//变化方向向下时削弱[-P~+P]->[(1-c)~1]
		DWK_P_DIR_DC,			//正向变化加强抑制能力 [-P~+P]->[(1+c)~1]->[2~1] ，反向变化削弱抑制能力[-P~+P]->[1~(1-c)]->[1~0]
		DWK_P_DIR_DN,			//正向变化削弱抑制能力 [-P~+P]->[(1-c)~1]->[0~1] ，反向变化增强抑制能力[-P~+P]->[1~(1+c)]->[1~2]
	} DV_WEAK_TYPE;


	/*死区类型*/
	typedef enum
	{
		DZ_MD_NOR = 0, 			//
		DZ_MD_NEV = 1, 			//仅小于设定值
		DZ_MD_PST = 2, 			//仅大于设定值
	} DEAD_ZONE_MODE_TYPE;

	typedef  struct
	{
		uint32_t check_err_cnt;
		DV_WEAK_TYPE dv_weak_type;			//外部更新  
		DEAD_ZONE_MODE_TYPE dead_zone_mode;	//外部更新    
		uint16_t kt_sv;			//外部更新，或调用update
		uint16_t kt_cnt;		//外部更新
		uint16_t kt_cycle;		//外部更新 //调用周期

		uint16_t P,I,D;			//外部更新，或调用update
		uint16_t Po,Io,Do,To; 	//内部

		int16_t iout_max;		//按照斜率计算，无斜率时取 iout_max_high
		int16_t iout_min;		//外部管理	-1000 - 1000
		int16_t iout_max_low;	//外部更新  或者调用 PidIoutSet， -1000-1000
		int16_t iout_max_high;	//外部更新  或者调用 PidIoutSet， -1000-1000 // svH == svL时采用该值
		int32_t iout_sv_low;	//外部更新  或者调用 PidIoutSet， iout_sv_high != iout_sv_high 时生效，线性范围
		int32_t iout_sv_high;	//外部更新  或者调用 PidIoutSet，
		float out_min;			//外部更新，或调用update
		float out_max;			//外部更新, 0-1000

		float sv;				//外部更新
		float pv;				//外部更新
		float out_fac;			//外部更新，输出规格化
		float out_offset;		//外部更新
		float dead_zone;		//外部更新
		
		float kp,ki,kd,dft;		//内部处理
		
		float dv_weak_coef;		//P点的削弱值，外部更新
		float dv_weak_max;		//最大削弱值，外部更新

		int32_t out;			//规格化输出   
		float out_adj;			//PID输出值
		float out_flt;			//输出滤波器
		float out_coef;			//0~1.0f//作用于削弱误差
		float out_coef_flt;		//0~0.99//递减系数
		float pv_old;
		float pvd;
		float uk;
	} pid_type;


	typedef  struct
	{
		uint32_t auto_set_time;
		uint8_t  ctr_dir;			//0:正向控制     1：反向控制
		uint8_t  state;				//0:不在自整定   FF:自整定结束
		uint16_t rise_time;
		uint16_t fall_time;
		uint16_t P;
		uint16_t I;
		uint16_t D;
		float pv;					//pid ==  0时使用
		float sv;					//pid ==  0时使用
		float  min;
		float  max;
		float  ctr_zone;			//输出回差带
		float  id_coef;				//微分积分比例
		pid_type *pid;				//0时使用本结构PvSv。非0跟随pid PvSv并在结束时自动更新PID参数
		void(*par_save)(void);		//计算pid自整定结束后调用外部保存函数
	} pid_tune_type;

	typedef struct
	{
		uint32_t check_err_cnt;
		//config
		uint8_t p_dis;				//Y 禁止P输出

		//timer
		uint16_t kt;				//Y
		uint16_t kt_cnt;			//X
		//input
		int32_t q_sv;				//Y // |sv-pv| < (q.32000) 无微分|sv-pv| < (q.64000)
		int32_t q_pv;				//Y // |sv-pv| < (q.32000) 无微分|sv-pv| < (q.64000)
		int32_t q_dead_zone;		//Y // 0~500
		int32_t q_ki_coef;			//Y积分系数 0~1
		//pid set
		int32_t q_p;				//Y // 0~(q.32000) 
		int16_t i;					//Y
		int16_t d;					//Y
		int32_t p_old;				//X
		int16_t i_old;
		int16_t d_old;
		uint16_t t_old;
		//middle value
		int32_t q_kp;				//X
		int32_t q_ki;				//X
		int32_t q_kd;				//X
		int32_t q_dft;				//X
		int32_t q_dv;				//X
		//process value
		int32_t q_ival;				//X
		int32_t q_imax;				//Y 千分数
		int32_t q_pv_old;			//X
		//limite
		int32_t q_max;				//Y 千分数
		int32_t q_min;				//Y 千分数
		//out
		int32_t q_out_flt;			//Y 输出滤波
		int32_t q_out;				//X 千分数
		int32_t q_out_fac;			//Y
		int16_t out;				//X 规格化
	} q_pid_type;

	// pid api
	void PidClr(pid_type* pid);//clear (dv,uk)    set(out_coef = 1)
	void PidDvClr(pid_type* pid); //clear dv
	void PidPvSet(pid_type* pid, float pv); //Set pv
	void PidSvSet(pid_type* pid, float sv); //Set sv

	void IndPid(pid_type* pid);

	void PidOutWeaken(pid_type* pid, float Coef);
	void PidUpdate(pid_type *pid, uint16_t *ParTab, float DutyMin, float DutyMax);
	void PidIoutSet(pid_type *pid, int16_t svL, int16_t svH, int16_t i_min_per, uint16_t i_max_per);//sv为设定值，per为输出百分比

	uint8_t PidAutoSet(pid_tune_type *tune_obj);
	void PidAutoSetStart(pid_type *pid, pid_tune_type *tune_obj);
	void PidAutoSetExit(pid_tune_type *tune_obj);
	void PidAutoSetCal(pid_tune_type *tune_obj);

	// q pid api
	int32_t q_pid_update(q_pid_type *pid);
	int32_t q_pid_cal(q_pid_type *pid);
	void q_pid_clr(q_pid_type *pid);
	void q_pid_dv_clr(q_pid_type *pid);


#undef PID_EXT

#ifdef	__cplusplus
}
#endif

#endif	/* PIDDEVICE_H */
